﻿using Infrastructure.Attribute;
using IP2Region.Ex.Models;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Protocol;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZR.DataCollection.ICommunication;
using ZR.DataCollection.InterfaceClass;
using ZR.DataCollection.Model;
using ZR.DataCollection.OperationCore.AbstractFactory;
using ZR.DataCollection.OperationCore.ExtensionMethod;
using ZR.DataCollection.OperationCore.OperationEnum;
using ZR.DataCollection.OperationCore.OperationHelper;
using ZR.DataCollection.SingleParameter;
using ZR.ServiceCore.Signalr;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace ZR.DataCollection.Execute
{
    /// <summary>
    /// 主要业务操作
    /// </summary>
    [AppService(ServiceType = typeof(IExecuteWork), ServiceLifetime = LifeTime.Singleton)]
    public class ExecuteMainWork : IExecuteWork
    {
        private readonly IHubContext<MessageHub> _hubContext;
        private readonly ILogger<ExecuteMainWork> _logger;
        private static readonly TaskQueue _taskQueue = new();
        private static readonly SemaphoreSlim _semaphore = new(10);

        public ExecuteMainWork(
            IHubContext<MessageHub> hubContext,
            ILogger<ExecuteMainWork> logger
            )
        {
            _hubContext = hubContext;
            _logger = logger;
        }

        public void ExecuteImport()
        {
            if (CurrentAppInfo.Current.InterfaceCommExtend != null)
            {
                CurrentAppInfo.Current.InterfaceCommExtend.CommunicationDataCallback += CommunicationDefault_plc_dataChange;
            }
        }

        public void CommunicationDefault_plc_dataChange(string stationType, INormCommunication communication, int itemNo, string address, object value)
        {
            try
            {
                IAbsStationFactory stationInfo = IAbsFactory.Current.GetStationFactory(stationType);
                ImpParameter imp = new ImpParameter()
                {
                    PLCDetail = communication,
                    objectParam = new DataDock()
                    {
                        ItemNo = itemNo,
                        LineCode = GetLineCode(stationType),
                        StationCode = stationType,
                        OrderCode = ProductInfoManager.Instance.GetOrderCode(stationType),
                        ProductCode = ProductInfoManager.Instance.GetOrderCode(stationType),
                        ProductType = ProductInfoManager.Instance.GetProductType(stationType),
                    }
                };
                //ItemNo是点位编号，将点位编号转换为对应的操作类型，获取具体的操作类
                IOperationModel operationInfo = stationInfo.GetOperationInfo(itemNo.OperationInfoByItem());
                operationInfo.Event_Notification += OperationInfo_Event_Notification;
                _taskQueue.Enqueue(async () =>
                {
                    await _semaphore.WaitAsync();
                    try
                    {
                        if (Convert.ToInt16(value).Equals(1))
                        {
                            await Task.Run(() => operationInfo.WorkDetail(imp));//执行作业
                        }
                        else
                        {
                            await Task.Run(() => operationInfo.SignalReset(imp));//信号复位
                        }
                    }
                    finally
                    {
                        _semaphore.Release();
                    }
                });
                Task.Run(() => _taskQueue.ProcessQueueAsync());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主要业务错误");
            }
        }

        private void OperationInfo_Event_Notification(string obj)
        {
            _logger.LogInformation(obj);
        }

        #region 参数获取

        private string GetLineCode(string stationCode)
        {
            return CurrentOPInfo.Current.WorkStationConfig.Find(f => f.WorkstationCode.Equals(stationCode, StringComparison.Ordinal)).ProductionLineCode;
        }

        #endregion 参数获取
    }
}